function [Atilde_MKT, Atilde_FUND, Atilde_NonMKT,v] = PortfolioLookthrough_ConnFunds_Analytical(A_MKT, A_FUND, A_NonMKT)

%%%% This function computes the analytical solution of the portfolio lookthrough (as in Internet Appendix A)

%%%%%%%%%%%

a = [A_MKT A_NonMKT];
TotalAssets = sum(A_FUND')' + sum(A_MKT')' + A_NonMKT;

C = sparse(A_FUND./repmat(TotalAssets',size(A_FUND,1),1));
Chat  = diag(1 - sum(C));
 
if min(Chat(:)) < 0
    % error('inconsistent fund holdings in sample!')
    Chat(Chat<0) = 0;
end

V = inv(eye(size(A_FUND,1)) - C)*a;
v = Chat*V;

%%%%%%%%%%%%%%%%%%%%%%%%%%

Atilde_MKT    = Chat*V(:,1:size(A_MKT,2));
Atilde_NonMKT = Chat*V(:,size(A_MKT,2)+1:end);
Atilde_FUND   = 0*A_FUND;

[sum(TotalAssets) sum(Atilde_MKT(:))+sum(Atilde_NonMKT(:))+sum(Atilde_FUND(:)) sum(A_FUND(:)) sum(Atilde_MKT(:))+sum(Atilde_NonMKT(:))+sum(Atilde_FUND(:))+sum(A_FUND(:))]


end

%%%% sanity check: the following function implements a sequential version
%%%% of the analytical solution. This yields the same results but is often
%%%% even faster. Uncomment if needed

% function [Atilde_MKT, Atilde_FUND, Atilde_NonMKT] = PortfolioLookthrough_ConnFunds_Sequential(A_MKT, A_FUND, A_NonMKT, threshold)
% 
% % for each fund, the aim is to iterate through its fund holdings and
% % distribute these holdings to the ultimate asset investments
% 
% if nargin < 4
%     threshold = 1e-6;
% end
% 
% TotalAssets = sum(A_FUND')' + sum(A_MKT')' + A_NonMKT;
% TotalAssets_tilde = TotalAssets;
% 
% Atilde_FUND    = A_FUND;
% Atilde_MKT     = A_MKT;
% Atilde_NonMKT  = A_NonMKT;
% 
% i_all  = find(sum(Atilde_FUND,2) > 0);
% nit = 0;
% 
% while isempty(i_all) == 0
%     
%     nit = nit + 1,
%     
%     %%%
%     n = randi(length(i_all));
%     
%     i        = i_all(n); 
%     i_all(n) = []; 
%     
%     %% step 1: add asset holdings of fund k prop to i's holdings of k
%     j = find(Atilde_FUND(i,:) > 0);
%     
%     s_ij        = Atilde_FUND(i, j)'./ TotalAssets_tilde(j);
% 
%     tmp_MKT     = repmat(s_ij,1,size(A_MKT,2)) .* Atilde_MKT(j, :);
%     tmp_NonMKT  = s_ij .* Atilde_NonMKT(j);
%     tmp_FUND    = repmat(s_ij,1,size(A_FUND,2)) .* Atilde_FUND(j, :);
%         
%     Atilde_MKT(i, :) = Atilde_MKT(i, :) + sum(tmp_MKT,1);
%     Atilde_NonMKT(i) = Atilde_NonMKT(i) + sum(tmp_NonMKT,1);
%     
%     %% step 2: same for fund holdings of fund k prop to i's holdings of k
%     Atilde_FUND(i, j) = 0;
%     Atilde_FUND(i, :) = Atilde_FUND(i, :) + sum(tmp_FUND,1);
%     
%     %% step 3: reduce portfolio holdings of k accordingly (and total assets)
%     Atilde_MKT(j, :) = Atilde_MKT(j, :) - tmp_MKT;
%     Atilde_NonMKT(j) = Atilde_NonMKT(j) - tmp_NonMKT;
%     Atilde_FUND(j,:) = Atilde_FUND(j,:) - tmp_FUND;
%     
%     TotalAssets_tilde(i) = sum(Atilde_FUND(i,:)) + sum(Atilde_MKT(i,:)) + Atilde_NonMKT(i);
%     TotalAssets_tilde(j) = sum(Atilde_FUND(j,:)')' + sum(Atilde_MKT(j,:)')' + Atilde_NonMKT(j);
%     
%     %% iterate until no further cross-fund holdings exist in Atilde_FUND
% 
%     if isempty(i_all) == 1;
%         i_all  = find(sum(Atilde_FUND,2) > 0);
%         
%         % for specific network constructions, the loop may run forever. for these cases,
%         % we add a "hard: threshold: stop if total investments after lookthrough are
%         % reasonably close to total assets. here 
%         
%         if sum(Atilde_FUND(:)) / sum(A_FUND(:)) < threshold %  || nit >= 10000
%            i_all = []; 
%         end
%     end
% end
% 
% % in some cases the relevant matrices include very small negative entries
% % (on the order of -1e-7): fix these!
% Atilde_MKT(Atilde_MKT < 0) = 0;
% Atilde_FUND(Atilde_FUND < 0) = 0;
% Atilde_NonMKT(Atilde_NonMKT < 0) = 0;
% 
% %%% final check
% [sum(TotalAssets) sum(Atilde_MKT(:))+sum(Atilde_NonMKT(:)) sum(Atilde_FUND(:))]
% 
% end
% 
% 
% 
